/*
 * %W% %E%
 *
 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package com.sun.corba.se.spi.extension ;

import org.omg.CORBA.Policy ;
import org.omg.CORBA.LocalObject ;
import com.sun.corba.se.impl.orbutil.ORBConstants ;

/** Policy used to implement servant caching optimization in the POA.
* Creating a POA with an instance pol of this policy where 
* pol.getType() &gt; NO_SERVANT_CACHING will cause the servant to be
* looked up in the POA and cached in the LocalClientRequestDispatcher when
* the ClientRequestDispatcher is colocated with the implementation of the
* objref.  This greatly speeds up invocations at the cost of violating the
* POA semantics.  In particular, every request to a particular objref
* must be handled by the same servant.  Note that this is typically the
* case for EJB implementations.
* <p>
* If servant caching is used, there are two different additional 
* features of the POA that are expensive:
* <ol>
* <li>POA current semantics
* <li>Proper handling of POA destroy.
* <ol>
* POA current semantics requires maintaining a ThreadLocal stack of
* invocation information that is always available for POACurrent operations.
* Maintaining this stack is expensive on the timescale of optimized co-located
* calls, so the option is provided to turn it off.  Similarly, causing 
* POA.destroy() calls to wait for all active calls in the POA to complete
* requires careful tracking of the entry and exit of invocations in the POA.
* Again, tracking this is somewhat expensive.
*/
public class ServantCachingPolicy extends LocalObject implements Policy
{
    /** Do not cache servants in the ClientRequestDispatcher.  This will 
     * always support the full POA semantics, including changing the
     * servant that handles requests on a particular objref.
     */
    public static final int NO_SERVANT_CACHING = 0 ;

    /** Perform servant caching, preserving POA current and POA destroy semantics.
    * We will use this as the new default, as the app server is making heavier use
    * now of POA facilities.
    */
    public static final int FULL_SEMANTICS = 1 ;

    /** Perform servant caching, preservent only POA current semantics.
    * At least this level is required in order to support selection of ObjectCopiers
    * for co-located RMI-IIOP calls, as the current copier is stored in 
    * OAInvocationInfo, which must be present on the stack inside the call.
    */
    public static final int INFO_ONLY_SEMANTICS =  2 ;

    /** Perform servant caching, not preserving POA current or POA destroy semantics.
    */
    public static final int MINIMAL_SEMANTICS = 3 ;

    private static ServantCachingPolicy policy = null ;
    private static ServantCachingPolicy infoOnlyPolicy = null ;
    private static ServantCachingPolicy minimalPolicy = null ;

    private int type ;
    
    public String typeToName()
    {
	switch (type) {
	    case FULL_SEMANTICS: 
		return "FULL" ;
	    case INFO_ONLY_SEMANTICS: 
		return "INFO_ONLY" ;
	    case MINIMAL_SEMANTICS: 
		return "MINIMAL" ;
	    default: 
		return "UNKNOWN(" + type + ")" ;
	}
    }

    public String toString() 
    {
	return "ServantCachingPolicy[" + typeToName() + "]" ;
    }

    private ServantCachingPolicy( int type ) 
    {
	this.type = type ;
    }

    public int getType()
    {
	return type ;
    }

    /** Return the default servant caching policy.
    */
    public synchronized static ServantCachingPolicy getPolicy()
    {
	return getFullPolicy() ;
    }

    public synchronized static ServantCachingPolicy getFullPolicy()
    {
	if (policy == null)
	    policy = new ServantCachingPolicy( FULL_SEMANTICS ) ;

	return policy ;
    }

    public synchronized static ServantCachingPolicy getInfoOnlyPolicy()
    {
	if (infoOnlyPolicy == null)
	    infoOnlyPolicy = new ServantCachingPolicy( INFO_ONLY_SEMANTICS ) ;

	return infoOnlyPolicy ;
    }

    public synchronized static ServantCachingPolicy getMinimalPolicy()
    {
	if (minimalPolicy == null)
	    minimalPolicy = new ServantCachingPolicy( MINIMAL_SEMANTICS ) ;

	return minimalPolicy ;
    }

    public int policy_type ()
    {
	return ORBConstants.SERVANT_CACHING_POLICY ;
    }

    public org.omg.CORBA.Policy copy ()
    {
	return this ;
    }

    public void destroy ()
    {
	// NO-OP
    }
}
